﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using MineDiscover.Utils;

namespace MineDiscover
{
    public class GameMineDiscover
    {
        // GameMineInstance
        private static readonly Object _lock = new Object();
        public static GameMineDiscover gameMineDiscover;

        private GameMineDiscover() { }
        
        public static GameMineDiscover GetInstance()
        {
            lock(_lock)
            {
                if (gameMineDiscover == null)
                {
                    gameMineDiscover = new GameMineDiscover();
                }
                return gameMineDiscover;
            }
        }

        // GAME
        public MapMine MapMine;
        public Difficulty Difficulty;

        // New Game
        public void InitalizeGame(Difficulty difficult)
        {
            Difficulty = difficult;
            MapMine = new MapMine(GameMineDiscover.GetInstance().Difficulty);
            IsStarted = false;
        }

        public bool IsStarted = false;

        public void StartGame(Point pointMouse, Size sizeMap)
        {
            Position position = GetPositionTile(pointMouse, sizeMap);
            RandomMine(position);
        }

        private void RandomMine(Position position)
        {
            List<Position> listPointArround = GetArround(position);

            int mine = Difficulty.Mine;
            List<Position> listPointMatrix = new List<Position>();
            
            for (int i = 0; i < Difficulty.Columns; i++)
            {
                for (int j = 0; j < Difficulty.Rows; j++)
                {
                    if (ComparePosition(listPointArround, new Position(i, j)))
                    {
                        listPointMatrix.Add(new Position(i, j));
                    }
                }
            }

            Random random = new Random();

            for (int i = 0; i < mine; i++)
            {
                int index = random.Next(0, listPointMatrix.Count);
                Position point = listPointMatrix[index];
                MapMine.Tiles[point.X, point.Y].IsMine = true;
                listPointMatrix.RemoveAt(index);
            }
        }

        public bool ComparePosition(List<Position> listPointArround, Position position)
        {
            
                if (listPointArround.Find(delegate(Position p) { return p.X == position.X && p.Y == position.Y; }) != null)
                {
                    return false;
                }
            
            return true;
        }

        public List<Position> GetArround(Position position)
        {
            // List Tile Arround New Game
            List<Position> listPointArround = new List<Position>();
            for (int i = 0; i < Helper.ArrayIndexArround.Length; i += 2)
            {
                int x = position.X + Helper.ArrayIndexArround[i];
                int y = position.Y + Helper.ArrayIndexArround[i + 1];

                if (Helper.ValidateOverBoundary(x, y, Difficulty.Rows, Difficulty.Columns))
                {
                    listPointArround.Add(new Position(x, y));
                }
            }
            return listPointArround;
        }
            
        public bool ValidateClickMine(Point pointMouse, Size sizeMap)
        {
            Position position = GetPositionTile(pointMouse, sizeMap);

            if (MapMine.Tiles[position.X, position.Y].TileState == TileState.Close && MapMine.Tiles[position.X, position.Y].IsMine)
            {
                return true;
            }
            return false;
        }

        private Position GetPositionTile(Point pointMouse, Size sizeMap)
        {
            SizeF sizeSquare = new SizeF((float)sizeMap.Width / (float)Difficulty.Columns, (float)sizeMap.Height / (float)Difficulty.Rows);
            int x = (int)(pointMouse.X / sizeSquare.Width);
            int y = (int)(pointMouse.Y / sizeSquare.Height);

            return new Position(x, y);
        }

        public bool Validate2Win(Point pointMouse, Size sizeMap)
        {
            int count = 0;

            for (int i = 0; i < Difficulty.Columns; i++)
            {
                for (int j = 0; j < Difficulty.Rows; j++)
                {
                    if (MapMine.Tiles[i, j].TileState == TileState.Open)
                    {
                        count++;
                    }
                }
            }

            if (count == (Difficulty.Rows * Difficulty.Columns) - Difficulty.Mine)
            {
                return true;
            }
            return false;
        }

        public int CountFlagInGame()
        {
            int count = Difficulty.Mine;

            for (int i = 0; i < Difficulty.Columns; i++)
            {
                for (int j = 0; j < Difficulty.Rows; j++)
                {
                    if (MapMine.Tiles[i, j].TileState == TileState.Flag)
                    {
                        count--;
                    }
                }
            }

            return count;
        }
    }
}
